package cn.xeblog.plugin.tools;

import cn.hutool.core.thread.GlobalThreadPool;
import cn.xeblog.commons.util.ThreadUtils;
import cn.xeblog.plugin.action.ConsoleAction;
import cn.xeblog.plugin.enums.Command;
import cn.xeblog.plugin.ui.MainWindow;
import com.intellij.openapi.application.ApplicationManager;

import javax.swing.JButton;
import javax.swing.JPanel;

/**
 * 面板组件抽象类
 *
 * @author anlingyi
 * @date 2022/8/5 6:18 上午
 */
public abstract class AbstractPanelComponent {

    /**
     * 主面板（即rightPanel右边的面板部分）
     */
    protected final JPanel mainPanel;

    /**
     * 初始化
     *
     * @param initialized 是否需要初始化
     */
    public AbstractPanelComponent(boolean initialized) {
        // 构建右边面板
        this.mainPanel = MainWindow.getInstance().getRightPanel();
        if (initialized) {
            // 初始化
            initialized();
        }
    }

    /**
     * 初始化
     */
    private void initialized() {
        // 初始化面板
        this.initMainPanel();
        // 初始化
        init();
        // 是否控制台消息一直在底部
        ConsoleAction.gotoConsoleLow(true);
    }

    /**
     * 初始化
     */
    protected abstract void init();

    /**
     * 关闭界面，结束使用
     */
    public void over() {
        invoke(() -> {
            mainPanel.setVisible(false);
            mainPanel.removeAll();
            mainPanel.updateUI();
        });
    }

    /**
     * 设置退出按钮，并绑定结果命令
     *
     * @return 按钮组件
     */
    protected JButton getExitButton() {
        JButton exitButton = new JButton("退出");
        exitButton.addActionListener(e -> Command.OVER.exec());
        return exitButton;
    }

    protected JButton getPrePageButton() {
        JButton exitButton = new JButton("返回");
        exitButton.addActionListener(e -> initialized());
        return exitButton;
    }

    /**
     * 调用
     *
     * @param runnable 任务
     */
    protected final void invoke(Runnable runnable) {
        ApplicationManager.getApplication().invokeLater(runnable);
    }

    /**
     * 调用
     *
     * @param runnable 任务
     * @param millis   自旋的时间（毫秒）
     */
    protected final void invoke(Runnable runnable, long millis) {
        GlobalThreadPool.execute(() -> {
            // 自旋
            spinMoment(millis);
            // 调用
            invoke(runnable);
        });
    }

    /**
     * 自旋
     *
     * @param millis 自旋的时间（毫秒）
     */
    protected void spinMoment(long millis) {
        ThreadUtils.spinMoment(millis);
    }

    /**
     * 初始化主面板
     */
    protected void initMainPanel() {
        // 移除全部面板
        mainPanel.removeAll();

        // 当前面板显示
        // 面板布局
        mainPanel.setLayout(null);
        // 设置此组件的首选大小
        mainPanel.setPreferredSize(null);
        // 设置启用此组件。已启用的组件可以响应用户输入，而未启用的组件则无法响应用户输入
        mainPanel.setEnabled(true);
        // 使该组件可见
        mainPanel.setVisible(true);
    }

}
